﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SWCInvoice.Servicelayer;
using System.IO;
using System.Collections.ObjectModel;
using System.ComponentModel;
using iTextSharp.text.pdf;
using SWCInvoice.ViewModel;

namespace SWCInvoice.Model {
    /// <summary>
    /// A virtual document structure
    /// </summary>
    /// <remarks>A virtual document structure contains all about a source pdf file. In first one it contains a list of documents.</remarks>
    public class VirtualDocumentStructure : ModelBase, IDisposable {

        #region Fields

        /// <summary>
        /// List of documents of the VDS
        /// </summary>
        private ObservableCollection<Document> _documents;
        /// <summary>
        /// ID of the VDS
        /// </summary>
        private string _id;

        /// <summary>
        /// Name of the linked sourcefile
        /// </summary>
        private string _fileName;

        /// <summary>
        /// Foldername of the linked sourcefile
        /// </summary>
        private string _folderName;

        /// <summary>
        /// Folderpath of the linked sourcefile
        /// </summary>
        private string _folderPath;

        ///// <summary>
        ///// Full filename of the linked sourcefile
        ///// </summary>
        //private int _fullFileName;
        ///// <summary>
        ///// Full folderpath of the linked sourcefile
        ///// </summary>
        //private string _fullFolderPath;
        /// <summary>
        /// Filename of the destinationfile
        /// </summary>
        private string _resultFileName;

        /// <summary>
        /// Foldername of the destinationfile
        /// </summary>
        private string _resultFolderName;

        /// <summary>
        /// Foldepath of the destinationfile
        /// </summary>
        private string _resultFolderPath;

        ///// <summary>
        ///// Full folderpath of the destinationfile
        ///// </summary>
        //private string _resultFullFolderPath;
        /// <summary>
        /// Gets or sets the basic result path name
        /// </summary>
        string _basicResultPathName;


        /// <summary>
        /// The PDF session path name 
        /// </summary>
        string _sessionPathName;

        /// <summary>
        /// The PDF merge path name
        /// </summary>
        string _mergePathName;

        /// <summary>
        /// The PDF documents path name
        /// </summary>
        string _documentsPathName;

        /// <summary>
        /// Name of the VDS
        /// </summary>
        private string _vdsName;

        /// <summary>
        /// The PDFReader instance
        /// </summary>
        private PdfReader _pdfInstance;

        /// <summary>
        /// The Pdf Info dictonary
        /// </summary>
        private Dictionary<string, string> _pdfInfo;

        /// <summary>
        /// The Pdf title
        /// </summary>
        private string _pdfTitle;

        /// <summary>
        /// The Pdf subject
        /// </summary>
        private string _pdfSubject;

        /// <summary>
        /// The Pdf producer
        /// </summary>
        private string _pdfProducer;

        /// <summary>
        /// The Pdf modification date
        /// </summary>
        private string _pdfModDate;

        /// <summary>
        /// The Pdf keywords
        /// </summary>
        private string _pdfKeywords;

        /// <summary>
        /// The Pdf filesize
        /// </summary>
        private string _pdfFilesize;

        /// <summary>
        /// The Pdf creator
        /// </summary>
        private string _pdfCreator;

        /// <summary>
        /// The Pdf creation date
        /// </summary>
        private string _pdfCreationDate;

        /// <summary>
        /// The Pdf Author
        /// </summary>
        private string _pdfAuthor;

        /// <summary>
        /// The Pdf number of pages
        /// </summary>
        private int? _pdfNumberOfPages;

        private bool isDisposed = false;
        #endregion

        #region Constructor

        /// <summary>
        /// Constructor of the virtual document structure object
        /// </summary>
        /// <param name="filenName">Name of the PDF file</param>
        /// <param name="name">Name of the vds</param>
        public VirtualDocumentStructure(string fileName, string name = "Session") {
            _id = Utilities.NewGuid();
            _vdsName = name;

            FileInfo fileInfo = new FileInfo(fileName);
            _fileName = fileInfo.Name;

            if (fileInfo.Directory.Parent != null) {
                _folderPath = fileInfo.Directory.Parent.FullName;
                _folderName = fileInfo.Directory.Name;
            } else {
                _folderPath = fileInfo.Directory.Name;
                _folderName = string.Empty;
            }

            _pdfInstance = new PdfReader(fileName);
            _pdfInfo = _pdfInstance.Info;

            
            try { PdfAuthor = _pdfInfo["Author"]; } catch { PdfAuthor = string.Empty; }
            try { PdfSubject = _pdfInfo["Subject"]; } catch { PdfSubject = string.Empty; }
            try { PdfKeywords = _pdfInfo["Keywords"]; } catch { PdfKeywords = string.Empty; }
            try { PdfCreationDate = Utilities.ConvertDate(_pdfInfo["CreationDate"].Substring(2), "yyyyMMddHHmmss").ToString();} catch { PdfCreationDate = string.Empty; }
            try { PdfModDate = Utilities.ConvertDate(_pdfInfo["ModDate"].Substring(2), "yyyyMMddHHmmss").ToString(); } catch { PdfModDate = string.Empty; }
            try { PdfCreator = _pdfInfo["Creator"]; } catch { PdfCreator = string.Empty; }
            try { PdfProducer = _pdfInfo["Producer"]; } catch { PdfProducer = string.Empty; }
            try { PdfTitle = _pdfInfo["Title"]; } catch { PdfTitle = string.Empty; }
            PdfNumberOfPages = _pdfInstance.NumberOfPages;                             
        }

        #endregion

        #region Destructor
        /// <summary>
        /// Destructor of the virtual document structure object
        /// </summary>
        ~VirtualDocumentStructure() {
            Dispose(false);
        }

        #endregion

        #region Properties

        /// <summary>
        /// ID of the VDS
        /// </summary>
        /// <value>A GUID value</value>
        public string ID {
            get {
                return _id;
            }
        }

        /// <summary>
        /// List of documents of the VDS
        /// </summary>
        public ObservableCollection<Document> Documents {
            get {
                if (_documents == null)
                    _documents = new ObservableCollection<Document>();
                return _documents;
            }
            set {
                if (_documents == value)
                    return;
                _documents = value;
                RaisePropertyChanged("Documents");
            }
        }

        /// <summary>
        /// Name of the linked sourcefile
        /// </summary>
        public string FileName {
            get {
                return _fileName;
            }
            set {
                if (_fileName == value)
                    return;
                _fileName = value;
                RaisePropertyChanged("FileName");
            }
        }

        /// <summary>
        /// Foldername of the linked sourcefile
        /// </summary>
        public string FolderName {
            get {
                return _folderName;
            }
        }

        /// <summary>
        /// Foldepath of the linked sourcefile
        /// </summary>
        public string FolderPath {
            get {
                return _folderPath;
            }
        }
        
        /// <summary>
        /// Full folderpath of the linked sourcefile
        /// </summary>
        /// <value>FolderPath+FolderName</value>
        public string FullFolderPath {
            get {
                return string.Format("{0}\\{1}", _folderPath, _folderName);
            }
        }

        /// <summary>
        /// Full filename of the linked sourcefile
        /// </summary>
        public string FullFileName {
            get {
                return string.Format("{0}\\{1}\\{2}", _folderPath, _folderName, _fileName);

            }
        }

        /// <summary>
        /// Name of the destinationfile
        /// </summary>
        public string ResultFileName {
            get {
                return _resultFileName;
            }
            set {
                if (_resultFileName == value)
                    return;
                _resultFileName = value;
                RaisePropertyChanged("ResultFileName");
            }
        }

        /// <summary>
        /// Foldername of the destinationfile
        /// </summary>
        public string ResultFolderName {
            get {
                return _resultFolderName;
            }
            set {
                if (_resultFolderName == value)
                    return;
                _resultFolderName = value;
                RaisePropertyChanged("ResultFolderName");
            }
        }

        /// <summary>
        /// Foldepath of the destinationfile
        /// </summary>
        public string ResultFolderPath {
            get {
                return _resultFolderPath;
            }
            set {
                if (_resultFolderPath == value)
                    return;
                _resultFolderPath = value;
                RaisePropertyChanged("ResultFolderPath");
            }
        }

        /// <summary>
        /// Full folderpath of the destinationfile
        /// </summary>
        /// <value>ResultFolderPath+ResultFolderName</value>
        public string ResultFullFolderPath {
            get {
                return string.Format("{0}\\{1}", _resultFolderPath, _resultFolderName);
            }
        }

        /// <summary>
        /// Full filename of the destinationfile
        /// </summary>
        public string ResultFullFileName {
            get {
                return string.Format("{0}\\{1}\\{2}", _resultFolderPath, _resultFolderName, _resultFileName);
            }
        }

        /// <summary>
        /// Gets or sets the basic result path name
        /// </summary>
        public string BasicResultPathName
        {
            get { return _basicResultPathName; }
            set
            {
                if (_basicResultPathName == value) return;
                _basicResultPathName = value;
                RaisePropertyChanged("BasicResultPathName");
            }
        }

        /// <summary>
        /// Gets or sets the session path name
        /// </summary>
        public string SessionPathName
        {
            get { return _sessionPathName; }
            set
            {
                if (_sessionPathName == value) return;
                _sessionPathName = value;
                RaisePropertyChanged("SessionPathName");
            }
        }

        /// <summary>
        /// Gets or sets the merge path name
        /// </summary>
        public string MergePathName
        {
            get { return _mergePathName; }
            set
            {
                if (_mergePathName == value) return;
                _mergePathName = value;
                RaisePropertyChanged("MergePathName");
            }
        }

        /// <summary>
        /// Gets or sets the merge path name
        /// </summary>
        public string DocumentsPathName
        {
            get { return _documentsPathName; }
            set
            {
                if (_documentsPathName == value) return;
                _documentsPathName = value;
                RaisePropertyChanged("DocumentsPathName");
            }
        }

        /// <summary>
        /// Name of the VDS
        /// </summary>
        public string VDSName {
            get {
                return _vdsName;
            }
            set {
                if (_vdsName == value)
                    return;
                _vdsName = value;
                RaisePropertyChanged("VDSName");
            }
        }

        /// <summary>
        /// The PDFReader instance
        /// </summary>
        public PdfReader PdfInstance {
            get {
                return _pdfInstance;
            }
            set {
                if (_pdfInstance == value)
                    return;
                _pdfInstance = value;
                RaisePropertyChanged("PdfInstance");
            }
        }

        /// <summary>
        /// The Pdf Info dictonary
        /// </summary>
        public Dictionary<string,string> PdfInfo {
            get {
                return _pdfInfo;
            }
            set {
                if (_pdfInfo == value)
                    return;
                _pdfInfo = value;
                RaisePropertyChanged("PdfInfo");
            }
        }

        /// <summary>
        /// The Pdf author
        /// </summary>
        public string PdfAuthor {
            get {
                return _pdfAuthor;
            }
            set {
                if (_pdfAuthor == value)
                    return;
                _pdfAuthor = value;
                RaisePropertyChanged("PdfAuthor");
            }
        }

        /// <summary>
        /// The Pdf subject
        /// </summary>
        public string PdfSubject {
            get {
                return _pdfSubject;
            }
            set {
                if (_pdfSubject == value)
                    return;
                _pdfSubject = value;
                RaisePropertyChanged("PdfSubject");
            }
        }

        /// <summary>
        /// The Pdf keywords
        /// </summary>
        public string PdfKeywords {
            get {
                return _pdfKeywords;
            }
            set {
                if (_pdfKeywords == value)
                    return;
                _pdfKeywords = value;
                RaisePropertyChanged("PdfKeywords");
            }
        }

        /// <summary>
        /// The Pdf creation date
        /// </summary>
        public string PdfCreationDate {
            get {
                return _pdfCreationDate;
            }
            set {
                if (_pdfCreationDate == value)
                    return;
                _pdfCreationDate = value;
                RaisePropertyChanged("PdfCreationDate");
            }
        }

        /// <summary>
        /// The Pdf mod date
        /// </summary>
        public string PdfModDate {
            get {
                return _pdfModDate;
            }
            set {
                if (_pdfModDate == value)
                    return;
                _pdfModDate = value;
                RaisePropertyChanged("PdfModDate");
            }
        }

        /// <summary>
        /// The Pdf creator
        /// </summary>
        public string PdfCreator {
            get {
                return _pdfCreator;
            }
            set {
                if (_pdfCreator == value)
                    return;
                _pdfCreator = value;
                RaisePropertyChanged("PdfCreator");
            }
        }

        /// <summary>
        /// The Pdf producer
        /// </summary>
        public string PdfProducer {
            get {
                return _pdfProducer;
            }
            set {
                if (_pdfProducer == value)
                    return;
                _pdfProducer = value;
                RaisePropertyChanged("PdfProducer");
            }
        }

        /// <summary>
        /// The Pdf title
        /// </summary>
        public string PdfTitle {
            get {
                return _pdfTitle;
            }
            set {
                if (_pdfTitle == value)
                    return;
                _pdfTitle = value;
                RaisePropertyChanged("PdfTitle");
            }
        }

        /// <summary>
        /// The Pdf filesize
        /// </summary>
        public string PdfFilesize {
            get {
                return string.Format("{0} MB ({1} Byte)", _pdfInstance.FileLength / 1048576, string.Format("{0:0,0}", _pdfInstance.FileLength));
            }
            set {
                if (_pdfFilesize == value)
                    return;
                _pdfFilesize = value;
                RaisePropertyChanged("PdfFilesize");
            }
        }

        /// <summary>
        /// The Pdf number of pages
        /// </summary>
        public int? PdfNumberOfPages {
            get {
                return _pdfNumberOfPages;
            }
            set {
                if (_pdfNumberOfPages == value)
                    return;
                _pdfNumberOfPages = value;
                RaisePropertyChanged("PdfNumberOfPages");
            }
        }

        #endregion

        #region Collection
        
        public class VirtualDocumentStructureCollection : ObservableCollection<VirtualDocumentStructure> {

        }

        #endregion

        #region Dispose

        protected void Dispose(bool disposing) {
            if (disposing) {
                // Code to dispose the managed resources of the class

                //FileName = null;               
                //ResultFileName = null;
                //ResultFolderName = null;
                //ResultFolderPath = null;
                //BasicResultPathName = null;
                //SessionPathName = null;
                //MergePathName = null;
                //DocumentsPathName = null;
                //VDSName = null;
                //PdfInstance = null;
                //PdfInfo = null;
                //PdfAuthor = null;
                //PdfCreationDate = null;
                //PdfCreator = null;
                //PdfFilesize = null;
                //PdfKeywords = null;
                //PdfModDate = null;
                //PdfNumberOfPages = null;
                //PdfProducer = null;
                //PdfSubject = null;
                //PdfTitle = null;

                foreach (Document item in Documents) {
                    item.Dispose();
                }
            }
            
            // Code to dispose the un-managed resources of the class
            isDisposed = true;
        }

        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion    
    }
}
